home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / bb212src / bbsrt232.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-02-11  |  19.9 KB  |  481 lines

  1. (*===========================================================================*)
  2. (* Procedure to send/receive things to the PK-232/PK-87 in host mode         *)
  3. (*                                                                           *)
  4. (*   Copyright 1988, 1989, 1990, 1991, 1992 by H. Roy Engehausen.  All       *)
  5. (*   rights reserved.                                                        *)
  6. (*                                                                           *)
  7. (*===========================================================================*)
  8.  
  9. (*===========================================================================*)
  10. (* Main procedure                                                            *)
  11. (*                                                                           *)
  12. (*    Parm = 0 -- Data                                                       *)
  13. (*           1 -- Data                                                       *)
  14. (*           2 -- General Poll                                               *)
  15. (*           3 -- Data Poll                                                  *)
  16. (*           4 -- Link Status Poll                                           *)
  17. (*           5 -- Data ack poll                                              *)
  18. (*===========================================================================*)
  19.  
  20. {$UNDEF DEBUG_232}
  21.  
  22. PROCEDURE send_recv_232(tnc_cmd_data : BYTE);
  23.  
  24.   LABEL
  25.     busy_loop;
  26.  
  27.   TYPE pk232_out = RECORD
  28.                      pk232_soh : CHAR;
  29.                      CASE INTEGER OF
  30.                        0 : ( pk232_ctl : BYTE;
  31.                              pk232_dat : ARRAY[1..649] OF CHAR);
  32.                        1 : (pk232_str  : STRING);
  33.                    END;
  34.  
  35.   CONST
  36.     pk232_general_command  = $4F;   (* General command                       *)
  37.     pk232_specific_command = $40;   (* Specific command to a channel         *)
  38.     pk232_specific_data    = $20;   (* Specific data to a channel            *)
  39.     pk232_general_data     = $29;   (* General command                       *)
  40.  
  41.     pk232_echo_data        = $2F;   (* Echoed data -- Not in packet mode     *)
  42.     pk232_incoming_data    = $30;   (* Incoming data w/channel number        *)
  43.     pk232_incoming_mon     = $3F;   (* Incoming monitor data                 *)
  44.     pk232_incoming_link    = $40;   (* Link status w/channel number          *)
  45.     pk232_incoming_cmd     = $4F;   (* Command response                      *)
  46.     pk232_incoming_link2   = $50;   (* Link status w/channel number          *)
  47.     pk232_incoming_status  = $5F;   (* Protocol status                       *)
  48.  
  49.   VAR
  50.     b           : BOOLEAN;
  51.     c           : CHAR;
  52.     data_switch : BOOLEAN;
  53.     i           : BYTE;
  54.     in_index    : WORD;
  55.     l_switch    : BOOLEAN;
  56.     l_str       : STRING[12];
  57.     lock_switch : BOOLEAN;
  58.     look_tcb    : tcb_ptr;
  59.     out_index   : WORD;
  60.     pk232_buff  : ^pk232_out;
  61.     pk232_chan  : BYTE;
  62.     pk232_len   : INTEGER;
  63.  
  64.   {$I BBSRT23I.PAS}              (* I/O Subroutines                          *)
  65.   {$I BBSRT23D.PAS}              (* Decode incoming packet to WA8DED format  *)
  66.  
  67.   BEGIN;
  68.  
  69.     (*-----------------------------------------------------------------------*)
  70.     (* Initialize                                                            *)
  71.     (*-----------------------------------------------------------------------*)
  72.  
  73.     pk232_buff := @active_tcb^.tnc_htt^;
  74.  
  75.     data_switch := tnc_cmd_data = info_cmd_info;
  76.  
  77.     l_switch := FALSE;
  78.  
  79.     (*-----------------------------------------------------------------------*)
  80.     (* Grab the port lock                                                    *)
  81.     (*-----------------------------------------------------------------------*)
  82.  
  83.     WITH active_port^, active_tcb^ DO
  84.       BEGIN;
  85.  
  86.         IF tnc_cmd_data = info_cmd_info THEN
  87.           BEGIN;
  88.  
  89.             (*---------------------------------------------------------------*)
  90.             (* Sending data so we have to wait for the all clear from the TNC*)
  91.             (* before proceeding                                             *)
  92.             (*---------------------------------------------------------------*)
  93.  
  94.             lock_switch := TRUE;
  95.  
  96.             (*---------------------------------------------------------------*)
  97.             (* Loop while we wait                                            *)
  98.             (*---------------------------------------------------------------*)
  99.  
  100.             WHILE lock_switch DO
  101.               BEGIN;
  102.  
  103.                 (*-----------------------------------------------------------*)
  104.                 (* Lock the port                                             *)
  105.                 (*-----------------------------------------------------------*)
  106.  
  107.                 get_semaphore(port_sema, sem_exclusive, FALSE);
  108.  
  109.                 (*-----------------------------------------------------------*)
  110.                 (* See if anyone else is waiting                             *)
  111.                 (*-----------------------------------------------------------*)
  112.  
  113.                 IF port_pk232_data_ack THEN
  114.                   BEGIN;
  115.  
  116.                     (*-------------------------------------------------------*)
  117.                     (* Someone else is waiting.  Free port and wait          *)
  118.                     (*-------------------------------------------------------*)
  119.  
  120.                     free_semaphore(port_sema);
  121.                     FOR i := 1 TO 10 DO
  122.                       task_switch;
  123.                   END
  124.                 ELSE
  125.                   BEGIN;
  126.  
  127.                     (*-------------------------------------------------------*)
  128.                     (* No one else is waiting.  Show that we are and let     *)
  129.                     (* out of loop                                           *)
  130.                     (*-------------------------------------------------------*)
  131.  
  132.                     port_pk232_data_ack := TRUE;
  133.                     lock_switch := FALSE;
  134.  
  135.                   END;
  136.  
  137.               END; (*----- End lock switch loop -----------------------------*)
  138.  
  139.           END (*----- End sending data --------------------------------------*)
  140.         ELSE
  141.  
  142.           (*-----------------------------------------------------------------*)
  143.           (* This is a command so we just get the lock                       *)
  144.           (*-----------------------------------------------------------------*)
  145.  
  146.           get_semaphore(port_sema, sem_exclusive, FALSE);
  147.  
  148.       END; (*---- End addressing --------------------------------------------*)
  149.  
  150.     (*-----------------------------------------------------------------------*)
  151.     (* This is where we loop to on a TNC busy                                *)
  152.     (*-----------------------------------------------------------------------*)
  153.  
  154. busy_loop:
  155.  
  156.     (*-----------------------------------------------------------------------*)
  157.     (* Recycle the port lock                                                 *)
  158.     (*-----------------------------------------------------------------------*)
  159.  
  160.     free_semaphore(active_port^.port_sema);
  161.     get_semaphore(active_port^.port_sema, sem_exclusive, FALSE);
  162.  
  163.     (*-----------------------------------------------------------------------*)
  164.     (* If this is a poll then we may have pending data already.  The         *)
  165.     (* tnc_data_queued routine will also dequeue the packet so its ready.    *)
  166.     (*-----------------------------------------------------------------------*)
  167.  
  168.     WITH active_tcb^ DO
  169.       IF (tnc_cmd_data > 1) AND (tnc_cmd_data < 5)
  170.                                                   AND (tnc_in_chn <> NIL) THEN
  171.         IF tnc_data_queued THEN
  172.           BEGIN;
  173.             free_semaphore(active_port^.port_sema);
  174.             EXIT;
  175.           END;
  176.  
  177.     (*-----------------------------------------------------------------------*)
  178.     (* Prevent execution if requested                                        *)
  179.     (*-----------------------------------------------------------------------*)
  180.  
  181.     WHILE active_tcb^.tcb_stop_tnc_io DO
  182.       task_switch;
  183.  
  184.     (*-----------------------------------------------------------------------*)
  185.     (* Start with an SOH                                                     *)
  186.     (*-----------------------------------------------------------------------*)
  187.  
  188.     pk232_buff^.pk232_soh := soh;
  189.  
  190.     (*-----------------------------------------------------------------------*)
  191.     (* See if special poll code                                              *)
  192.     (*-----------------------------------------------------------------------*)
  193.  
  194.     IF tnc_cmd_data > 1 THEN
  195.       WITH pk232_buff^ DO
  196.         BEGIN;
  197.  
  198.           (*-----------------------------------------------------------------*)
  199.           (* Special poll.  Issue GG                                         *)
  200.           (*-----------------------------------------------------------------*)
  201.  
  202.           pk232_ctl    := pk232_general_command;
  203.           pk232_dat[1] := 'G';
  204.           pk232_dat[2] := 'G';
  205.           pk232_dat[3] := etb;
  206.           pk232_len    := 5;
  207.  
  208.         END
  209.     ELSE
  210.       WITH pk232_buff^, active_tcb^ DO
  211.         BEGIN;
  212.  
  213.           (*-----------------------------------------------------------------*)
  214.           (* Send command or data                                            *)
  215.           (*-----------------------------------------------------------------*)
  216.  
  217.           IF tnc_cmd_data = info_cmd_info THEN
  218.             BEGIN;
  219.  
  220.               (*-------------------------------------------------------------*)
  221.               (* Send data                                                   *)
  222.               (*-------------------------------------------------------------*)
  223.  
  224.               IF channel > 0 THEN
  225.                 pk232_ctl := pk232_specific_data + channel - 1
  226.               ELSE
  227.                 pk232_ctl := pk232_general_data;
  228.               data_switch := TRUE;
  229.  
  230.             END
  231.           ELSE
  232.             BEGIN;
  233.  
  234.               (*-------------------------------------------------------------*)
  235.               (* Send command                                                *)
  236.               (*-------------------------------------------------------------*)
  237.  
  238.               IF channel > 0 THEN
  239.                 pk232_ctl := pk232_specific_command + channel - 1
  240.               ELSE
  241.                 pk232_ctl := pk232_general_command;
  242.  
  243.               (*-------------------------------------------------------------*)
  244.               (* Map DED commands into their PK232 counterparts              *)
  245.               (*-------------------------------------------------------------*)
  246.  
  247.               WITH tnc_data DO
  248.                 BEGIN;
  249.  
  250.                   IF str_data = 'L' THEN     (* L = CO                       *)
  251.                     BEGIN;
  252.                       str_data := 'CO';
  253.                       l_switch := TRUE;
  254.                     END
  255.                   ELSE
  256.                     IF str_data = 'D' THEN   (* D = DI                       *)
  257.                       str_data := 'DI'
  258.                     ELSE
  259.                       IF (str_data[1] = 'C') AND (str_data[2] = ' ') AND
  260.                            (LENGTH(str_data) > 2) THEN    (* C = CO          *)
  261.                          str_data[2] := 'O'
  262.                        ELSE
  263.                          BEGIN;
  264.                            str_data[1] := UPCASE(str_data[1]);
  265.                            str_data[2] := UPCASE(str_data[2]);
  266.                          END;
  267.  
  268.                   long_length := LENGTH(str_data);
  269.  
  270.                 END; (*----- End addressing of TNC_DATA ---------------------*)
  271.  
  272.             END;
  273.  
  274.           (*-----------------------------------------------------------------*)
  275.           (* Now transfer the data to the buffer inserting the DLE as needed *)
  276.           (*-----------------------------------------------------------------*)
  277.  
  278.           in_index  := 0;
  279.           out_index := 0;
  280.  
  281.           WITH tnc_data DO
  282.             WHILE in_index < tnc_data.long_length DO
  283.               BEGIN;
  284.  
  285.                 INC(in_index);
  286.                 INC(out_index);
  287.                 c := long_data[in_index];
  288.                 IF (c = soh) OR (c = etb) OR (c = dle) THEN
  289.                   BEGIN;
  290.                     pk232_dat[out_index] := dle;
  291.                     INC(out_index);
  292.                   END;
  293.  
  294.                 pk232_dat[out_index] := c;
  295.  
  296.               END;
  297.  
  298.           (*-----------------------------------------------------------------*)
  299.           (* Put the ETB on the end                                          *)
  300.           (*-----------------------------------------------------------------*)
  301.  
  302.           pk232_dat[out_index + 1] := etb;
  303.           pk232_len := out_index + 3;
  304.  
  305.         END;
  306.  
  307.     {$IFDEF DEBUG_232}
  308.       WITH pk232_buff^ DO
  309.         WRITELN('Sending =', pk232_ctl, pk232_dat[1],
  310.                                         pk232_dat[2],
  311.                                     ORD(pk232_dat[3]));
  312.     {$ENDIF}
  313.  
  314.     (*-----------------------------------------------------------------------*)
  315.     (* Now get the main lock                                                 *)
  316.     (*-----------------------------------------------------------------------*)
  317.  
  318.     get_semaphore(semaphore_interrupts, sem_shared, FALSE);
  319.  
  320.     (*-----------------------------------------------------------------------*)
  321.     (* Do the I/O                                                            *)
  322.     (*-----------------------------------------------------------------------*)
  323.  
  324.     pk232_io;
  325.  
  326.     {$IFDEF DEBUG_232}
  327.       WITH pk232_buff^ DO
  328.         WRITELN('Recving =', pk232_ctl, pk232_dat[1],
  329.                                         pk232_dat[2],
  330.                                     ORD(pk232_dat[3]));
  331.     {$ENDIF}
  332.  
  333.     (*-----------------------------------------------------------------------*)
  334.     (* Free the main lock                                                    *)
  335.     (*-----------------------------------------------------------------------*)
  336.  
  337.     free_semaphore(semaphore_interrupts);
  338.  
  339.     task_switch;
  340.  
  341.     (*-----------------------------------------------------------------------*)
  342.     (* If we sent data then loop back to do a poll                           *)
  343.     (*-----------------------------------------------------------------------*)
  344.  
  345.     IF data_switch AND (tnc_cmd_data = info_cmd_info) THEN
  346.       BEGIN;
  347.         tnc_cmd_data := 5;
  348.         GOTO busy_loop;
  349.       END;
  350.  
  351.     (*-----------------------------------------------------------------------*)
  352.     (* Quick sanity check                                                    *)
  353.     (*-----------------------------------------------------------------------*)
  354.  
  355.     IF pk232_len < 4 THEN
  356.       window_write_critical_i('Invld PK-232 Len -- '
  357.                                             + active_tcb^.port_chan_s + ' -- ',
  358.                                pk232_len);
  359.  
  360.     (*-----------------------------------------------------------------------*)
  361.     (* Data has arrived                                                      *)
  362.     (*-----------------------------------------------------------------------*)
  363.  
  364.     WITH active_tcb^.tnc_data, pk232_buff^ DO
  365.       BEGIN;
  366.  
  367.         (*-------------------------------------------------------------------*)
  368.         (* Decode data as needed                                             *)
  369.         (*-------------------------------------------------------------------*)
  370.  
  371.         pk232_decode;
  372.  
  373.         (*-------------------------------------------------------------------*)
  374.         (* Move data from TNC buffer into data buffer                        *)
  375.         (*-------------------------------------------------------------------*)
  376.  
  377.         in_index  := 0;
  378.         out_index := 0;
  379.         WHILE in_index < (pk232_len-3) DO
  380.           BEGIN;
  381.             INC(in_index);
  382.             INC(out_index);
  383.             c := pk232_dat[in_index];
  384.             IF c = dle THEN
  385.               BEGIN;
  386.                 INC(in_index);
  387.                 c := pk232_dat[in_index];
  388.               END;
  389.             long_data[out_index] := c;
  390.           END;
  391.  
  392.         long_length := out_index;
  393.         IF long_length > 255 THEN
  394.           str_data[0] := CHR(255)
  395.         ELSE
  396.           str_data[0] := CHR(long_length);
  397.  
  398.         (*-------------------------------------------------------------------*)
  399.         (* OK... Now for the biggy.  Did we get data for another channel.    *)
  400.         (* The PK232 only has a "general channel poll" so the data could     *)
  401.         (* be for anyone.                                                    *)
  402.         (*-------------------------------------------------------------------*)
  403.  
  404.         WITH active_tcb^ DO
  405.           IF (pk232_chan <> channel)
  406.                            OR ((tnc_cmd_data = 5) AND (long_length <> 0)) THEN
  407.             BEGIN;
  408.  
  409.               (*-------------------------------------------------------------*)
  410.               (* Sanity check for valid channel number                       *)
  411.               (*-------------------------------------------------------------*)
  412.  
  413.               IF pk232_chan > active_port^.max_chan THEN
  414.                 BEGIN;
  415.                   window_write_critical_i('Invld chan no from PK-232 -- '
  416.                                                         + port_chan_s + ' -- ',
  417.                                            pk232_chan);
  418.                   pk232_chan := 0;
  419.                 END;
  420.  
  421.               (*-------------------------------------------------------------*)
  422.               (* Find out what TCB applies to this channel.  If none, use the*)
  423.               (* AUX task                                                    *)
  424.               (*-------------------------------------------------------------*)
  425.  
  426.               look_tcb := active_port^.connected^[pk232_chan];
  427.               IF look_tcb = NIL THEN
  428.                 look_tcb := active_port^.aux_thread;
  429.  
  430.               (*-------------------------------------------------------------*)
  431.               (* Add info to queue                                           *)
  432.               (*-------------------------------------------------------------*)
  433.  
  434.               {$IFDEF DEBUG_232}
  435.                 WRITELN('chaining from ', channel, ' to ', pk232_chan, '/',
  436.                                                         look_tcb^.port_chan_s);
  437.               {$ENDIF}
  438.  
  439.               add_tnc_queue(look_tcb, pk232_chan);
  440.  
  441.               (*-------------------------------------------------------------*)
  442.               (* Go back and poll for this channel again                     *)
  443.               (*-------------------------------------------------------------*)
  444.  
  445.               GOTO busy_loop;
  446.  
  447.             END;
  448.  
  449.         (*-------------------------------------------------------------------*)
  450.         (* Set null indicator                                                *)
  451.         (*-------------------------------------------------------------------*)
  452.  
  453.         WITH active_tcb^ DO
  454.           tnc_null := long_length = 0;
  455.  
  456.         (*-------------------------------------------------------------------*)
  457.         (* If we are waiting for a data ACK, loop if we didn't get one       *)
  458.         (*-------------------------------------------------------------------*)
  459.  
  460.         WITH active_port^ DO
  461.           IF (tnc_cmd_data = 5) AND port_pk232_data_ack THEN
  462.             BEGIN;
  463.               FOR i := 1 TO 10 DO
  464.                 task_switch;
  465.               GOTO busy_loop;
  466.             END;
  467.  
  468.         {$IFDEF DEBUG_232}
  469.           WRITELN('NULL=', active_tcb^.tnc_null);
  470.         {$ENDIF}
  471.  
  472.       END; (*---- End WITH for the buffers ----------------------------------*)
  473.  
  474.     (*-----------------------------------------------------------------------*)
  475.     (* Free the port lock                                                    *)
  476.     (*-----------------------------------------------------------------------*)
  477.  
  478.     free_semaphore(active_port^.port_sema);
  479.  
  480.   END; (*----- End main send/receive TNC ------------------------------------*)
  481.